package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.Destination;
import cn.wolfcode.wolf2w.domain.Travel;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.exception.LogicException;
import cn.wolfcode.wolf2w.query.TravelCondition;
import cn.wolfcode.wolf2w.query.TravelQuery;
import cn.wolfcode.wolf2w.repository.TravelRepository;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.ITravelService;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * 游记业务层的实现类
 */
@Service
public class TravelServiceImpl implements ITravelService {

    //  注入TravelRepository持久层接口
    @Autowired
    private TravelRepository travelRepository;

    @Autowired
    private IUserInfoService userInfoService;

    @Autowired
    private IDestinationService destinationService;

    //  注入MongoTemplate服务
    @Autowired
    private MongoTemplate mongoTemplate;

    //  插入单个方法
    @Override
    public void insert(Travel travel) {

        //  id自动生成，手动设置为空
        travel.setId(null);

        //  调用持久层接口的save方法执行插入单个游记对象
        travelRepository.save(travel);

    }

    //  删除单个方法
    @Override
    public void deleteById(String id) {

        //  调用持久层接口的deleteById方法执行删除单个游记对象
        travelRepository.deleteById(id);
    }

    //  修改单个方法
    @Override
    public void updateById(Travel travel) {

        //  调用持久层接口的save方法执行修改单个游记对象
        travelRepository.save(travel);
    }

    //  查询单个方法
    @Override
    public Travel selectById(String id) {
        
        //  调用持久层接口的findById方法执行查询单个游记对象
        Travel travel = travelRepository.findById(id).orElse(null);

        if (travel != null) {
            travel.setAuthor(userInfoService.selectById(travel.getUserId()));
            travel.setDest(destinationService.selectById(travel.getDestId()));
        }

        return travel;
    }

    //  查询所有方法
    @Override
    public List<Travel> selectAll() {

        //  调用持久层接口的findAll方法执行查询所有游记对象
        return travelRepository.findAll();
    }

    //  分页方法
    @Override
    public Page<Travel> query(TravelQuery qo) {

        //  查询对象
        Query query = new Query();

        if (qo.getState() == -1) {
            query.addCriteria(Criteria.where("state").is(Travel.STATE_REJECT));
        } else if (qo.getState() == 1) {
            query.addCriteria(Criteria.where("state").is(Travel.STATE_WAITING));
        } else if (qo.getState() == 0){
            query.addCriteria(Criteria.where("state").is(Travel.STATE_RELEASE));
        }

        if (StringUtils.hasLength(qo.getDestId())) {
            query.addCriteria(Criteria.where("destId").is(qo.getDestId()));
        }

        TravelCondition days = qo.getDays();
        if (days != null) {
            query.addCriteria(Criteria.where("day").gte(days.getMin()).lte(days.getMax()));
        }

        TravelCondition perExpends = qo.getPerExpends();
        if (perExpends != null) {
            query.addCriteria(Criteria.where("perExpend").gte(perExpends.getMin()).lte(perExpends.getMax()));
        }

        //  调用mongodb服务中的count方法
        //  传入上面的查询对象和Travel的字节码对象
        //  返回一个满足条件的总记录数
        long totalCount = mongoTemplate.count(query, Travel.class);

        //  若查询出来的总记录数为零时
        if (totalCount == 0) {

            //  直接返回一个空集合
            return Page.empty();
        }

        Pageable pageable;
        if (qo.getOrderType() == 1) {
            //  调用Pageable的of方法
            //  传入qo对象的当前页，qo对象的当前页显示的最大记录数，排序的顺序，通过_id来排序
            pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "createTime");
        } else if (qo.getOrderType() == 2) {
            pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "viewnum");
        } else {
            pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.ASC, "_id");
        }

        //  把限制条件加入到查询对象中
        query.with(pageable);

        //  调用mongodb服务中的find方法
        //  传入上面的查询对象和Travel的字节码对象
        //  返回一个满足条件的游记对象的集合数据
        List<Travel> travels = mongoTemplate.find(query, Travel.class);

        //  返回一个PageImpl的集合
        //  传入一个满足条件的游记对象的集合数据对象
        //  传入限制条件
        //  返回一个满足条件的总记录数
        PageImpl<Travel> travelPage = new PageImpl<>(travels, pageable, totalCount);

        //  循环遍历travelPage集合
        //  拿到满足查询条件的travel对象
        for (Travel travel : travelPage) {

            //  通过获取游记的用户id来查询用户并设置到游记对象中
            travel.setAuthor(userInfoService.selectById(travel.getUserId()));
        }

        //  返回集合
        return travelPage;
    }

    //  查看文章
    @Override
    public String getContentById(String id) {
        Travel travel = this.selectById(id);
        return travel.getContent();
    }

    //  拒绝/待发布
    @Override
    public void audit(String id, int state) {
        //  查询
        Travel travel = this.selectById(id);

        //  判断是否满足审核条件
        //  判空
        if (travel == null) {
            throw new LogicException("参数异常");
        }

        //  判是否为待审核状态
        if (travel.getState() == Travel.STATE_WAITING) {

            //  审核通过之后要做什么
            if (state == Travel.STATE_RELEASE) {
                //  修改状态为审核状态
                travel.setState(Travel.STATE_RELEASE);
                //  获取之前创建时间
                travel.setCreateTime(travel.getCreateTime());
                //  修改发布时间
                travel.setReleaseTime(DateUtil.getTime());
                //  最后更新时间
                travel.setLastUpdateTime(DateUtil.getTime());
                //  记录审核信息
                this.updateById(travel);
            }

            //  审核拒绝之后要做什么
            if (state == Travel.STATE_REJECT) {
                //  修改状态为审核拒绝状态
                travel.setState(Travel.STATE_REJECT);
                //  获取之前创建时间
                travel.setCreateTime(travel.getCreateTime());
                //  修改发布时间（null）
                travel.setReleaseTime(null);
                //  最后更新时间
                travel.setLastUpdateTime(DateUtil.getTime());
                //  记录审核信息
                this.updateById(travel);
            }

        }

        //  判是否为发布状态
        if (travel.getState() == Travel.STATE_RELEASE) {
            //  下架操作
            if (state == Travel.STATE_WAITING) {
                //  修改状态待发布状态
                travel.setState(Travel.STATE_WAITING);
                //  获取之前创建时间
                travel.setCreateTime(travel.getCreateTime());
                //  修改发布时间（null）
                travel.setReleaseTime(null);
                //  最后更新时间
                travel.setLastUpdateTime(DateUtil.getTime());
                //  记录审核信息
                this.updateById(travel);
            }
        }


    }

    //  添加/更新
    @Override
    public void saveOrUpdate(Travel travel) {

        //  目的地名称
        Destination destination = destinationService.selectById(travel.getDestId());
        travel.setDestName(destination.getName());

        //  最后修改时间
        travel.setLastUpdateTime(DateUtil.getTime());

        if (StringUtils.hasLength(travel.getId())) {
            //  创建时间
            Travel tv = this.selectById(travel.getId());
            travel.setCreateTime(tv.getCreateTime());
            this.updateById(travel);
        } else {
            //  创建时间
            travel.setCreateTime(DateUtil.getTime());
            this.insert(travel);
        }

    }

    //  游记热门前三
    @Override
    public List<Travel> queryViewmunTop3(String destId) {

       Pageable pageable = PageRequest.of(0, 3, Sort.Direction.DESC, "viewnum");

       List<Travel> travelList = travelRepository.findByDestId(destId, pageable);

        return travelList;
    }

    @Override
    public List<Travel> queryDestName(String keyword) {
        List<Travel> travelList = travelRepository.findByDestName(keyword);

        for (Travel travel : travelList) {
            travel.setAuthor(userInfoService.selectById(travel.getUserId()));
            travel.setDest(destinationService.selectById(travel.getDestId()));
        }

        return travelList;
    }

}
